package com.woonoz.network.windows;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.prefs.Preferences;

public class WindowsRegistryReader {

	private static final int KEY_READ = 0x20019;
	
	private final Method openKey;
	private final Method closeKey;
	private final Method winRegQueryValue;
	private final Method winRegEnumValue;
	private final Method winRegQueryInfo;
	private final Preferences userRoot;
	private final Preferences systemRoot;
	
	public WindowsRegistryReader() throws SecurityException, NoSuchMethodException {
		userRoot = Preferences.userRoot();
		systemRoot = Preferences.systemRoot();
		final Class<? extends Preferences> clz = userRoot.getClass();
		
		openKey = clz.getDeclaredMethod("openKey", byte[].class, int.class, int.class);
		openKey.setAccessible(true);

		closeKey = clz.getDeclaredMethod("closeKey", int.class);
		closeKey.setAccessible(true);

		winRegQueryValue = clz.getDeclaredMethod("WindowsRegQueryValueEx", int.class, byte[].class);
		winRegQueryValue.setAccessible(true);
		
		winRegEnumValue = clz.getDeclaredMethod("WindowsRegEnumValue1", int.class, int.class, int.class);
		winRegEnumValue.setAccessible(true);
		
		winRegQueryInfo = clz.getDeclaredMethod("WindowsRegQueryInfoKey1", int.class);
		winRegQueryInfo.setAccessible(true);

	}
	
	public String readUserKey(final String path, final String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		return readUserKey(userRoot, path, key);
	}
	
	public String readSystemKey(final String path, final String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		return readUserKey(systemRoot, path, key);
	}
	
	private String readUserKey(final Preferences prefs, final String path, final String key) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		final Integer handle = (Integer) openKey.invoke(prefs, toCstr(path), KEY_READ, KEY_READ);
		final byte[] valb = (byte[]) winRegQueryValue.invoke(prefs, handle.intValue(), toCstr(key));
		final String vals = (valb != null ? new String(valb).trim() : null);
		closeKey.invoke(prefs, handle);
		return vals;
	}

	private static byte[] toCstr(final String str) {
		byte[] result = new byte[str.length() + 1];
		for (int i = 0; i < str.length(); i++) {
			result[i] = (byte) str.charAt(i);
		}
		result[str.length()] = 0;
		return result;
	}
}
